package com.benson.common.cron.controller;


import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.benson.common.common.entity.Pagination;
import com.benson.common.common.entity.ResultPoJo;
import com.benson.common.common.exception.MyBaselogicException;
import com.benson.common.common.util.CommonUtil;
import com.benson.common.cron.annotation.CronConfig;
import com.benson.common.cron.dto.CronQueryDto;
import com.benson.common.cron.dto.CronSaveDto;
import com.benson.common.cron.entity.Cron;
import com.benson.common.cron.entity.CronCommonConfig;
import com.benson.common.cron.service.ICronService;
import com.benson.common.cron.util.QuartzUtils;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 定时任务表 前端控制器
 * </p>
 *
 * @author zhangby
 * @since 2020-02-24
 */
@RestController
@RequestMapping("/cron")
@Api(tags = "定时任务管理")
public class CronController {

    @Autowired
    ICronService cronService;

    @Autowired
    private Scheduler scheduler;

    @Autowired
    CronCommonConfig cronCommonConfig;

    /**
     * 分页查询
     *
     * @return
     */
    @GetMapping("")
    @ApiOperation(value = "分页查询", notes = "分页查询", produces = "application/json")
    public ResultPoJo<IPage<Cron>> getCron4Page(Pagination pagination, CronQueryDto cronQueryDto) {
        LambdaQueryWrapper<Cron> queryWrapper = cronQueryDto.queryWrapper();
        IPage page = cronService.page(pagination.page(), queryWrapper);
        CommonUtil.convers(page.getRecords(), cronService.initCron());
        return ResultPoJo.ok(page);
    }

    /**
     * 查询定时任务详情
     *
     * @return
     */
    @GetMapping("/{id}")
    @ApiOperation(value = "查询定时任务详情", notes = "查询定时任务详情", produces = "application/json")
    public ResultPoJo<Cron> getCronById(@PathVariable String id) {
        Cron cron = cronService.getById(id);
        return ResultPoJo.ok(cronService.initCron().apply(cron));
    }

    /**
     * 保存定时任务
     *
     * @return
     */
    @PostMapping("")
    @ApiOperation(value = "保存定时任务", notes = "保存定时任务", produces = "application/json")
    public ResultPoJo saveCron(@Validated @RequestBody CronSaveDto cronSaveDto) {
        Cron cron = cronSaveDto.convert();
        /** 验证是否已经存在，相同定时任务 */
        Cron dbCron = cronService.getOne(
                new LambdaQueryWrapper<Cron>()
                        .eq(Cron::getMark, cron.getMark())
                , false);
        if (ObjectUtil.isNotNull(dbCron)) {
            throw new MyBaselogicException("999", cronSaveDto.getMark() + "，定时任务已存在，不可重复添加");
        }
        cron.preInsert();
        cronService.save(cron);
        // 更新定时任务
        QuartzUtils.updateScheduleJob4CronId(scheduler, cron.getId());
        return ResultPoJo.ok();
    }

    /**
     * 更新定时任务
     *
     * @return
     */
    @PutMapping("/{id}")
    @ApiOperation(value = "更新定时任务", notes = "更新定时任务", produces = "application/json")
    public ResultPoJo updateCron(@PathVariable String id, @Validated @RequestBody CronSaveDto cronSaveDto) {
        Cron cron = cronSaveDto.convert().setId(id);
        /** 验证是否已经存在，相同定时任务 */
        Cron dbCron = cronService.getOne(
                new LambdaQueryWrapper<Cron>()
                        .eq(Cron::getMark, cron.getMark())
                        .ne(Cron::getId, id)
                , false);
        if (ObjectUtil.isNotNull(dbCron)) {
            throw new MyBaselogicException("999", cronSaveDto.getMark() + "，定时任务已存在，不可重复添加");
        }
        cron.preUpdate();
        cronService.updateById(cron);
        // 更新定时任务
        QuartzUtils.updateScheduleJob4CronId(scheduler, cron.getId());
        return ResultPoJo.ok();
    }

    /**
     * 删除定时任务
     *
     * @return
     */
    @DeleteMapping("/{id}")
    @ApiOperation(value = "删除定时任务", notes = "删除定时任务", produces = "application/json")
    public ResultPoJo deleteCron(@PathVariable String id) {
        cronService.removeByIds(Lists.newArrayList(id.split(",")));
        return ResultPoJo.ok();
    }

    /**
     * 获取系统定时任务
     *
     * @return
     */
    @GetMapping("/get/system/cron/data")
    @ApiOperation(value = "获取系统定时任务", notes = "获取系统定时任务", produces = "application/json")
    public ResultPoJo<List<String>> getSystemCronData() {
        Set<Class<?>> classes = ClassUtil.scanPackage(cronCommonConfig.getScanPackage());
        List<Dict> rsList = classes.stream()
                .map(clazz -> clazz.getAnnotation(CronConfig.class))
                .filter(item -> ObjectUtil.isNotNull(item))
                .map(item -> Dict.create()
                        .set("label", CommonUtil.notEmpty(item.description()).orElse(item.value()))
                        .set("value", item.value())
                )
                .collect(Collectors.toList());
        return ResultPoJo.ok(rsList);
    }
}

